package com.gitee.flwwsg.rpc.transport.netty;

import com.gitee.flwwsg.rpc.transport.RequestHandler;
import com.gitee.flwwsg.rpc.transport.RequestHandlerRegistry;
import com.gitee.flwwsg.rpc.transport.command.Command;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RequestInvocation extends SimpleChannelInboundHandler<Command> {

    private static final Logger logger = LoggerFactory.getLogger(RequestInvocation.class);
    private final RequestHandlerRegistry registry;

    RequestInvocation(RequestHandlerRegistry registry) {
        this.registry = registry;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Command msg) throws Exception {
        //移除已经处理的消息
        RequestHandler handler = registry.get(msg.getHeader().getType());
        if (null != handler) {
            Command response = handler.handle(msg);
            if (null != response) {
                ctx.writeAndFlush(response).addListener((ChannelFutureListener) channelFuture -> {
                    if (!channelFuture.isSuccess()) {
                        logger.warn("write response failed", channelFuture.cause());
                        ctx.channel().close();
                    }
                });
            } else {
                logger.warn("response is null");
            }
        } else {
            throw new Exception(String.format("no handler for request with type: %d!", msg.getHeader().getType()));
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.warn("Exception: ", cause);
        super.exceptionCaught(ctx, cause);
        Channel channel = ctx.channel();
        if (channel.isActive()) {
            ctx.close();
        }
    }
}
